/**
 * 
 */
package any.tag.server.resource;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;

import javax.activation.FileTypeMap;

import org.apache.commons.lang.StringUtils;
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import any.restlet.helper.RepresentationHelper;
import any.tag.TagItem;
import any.tag.server.TagService;

/**
 * TODO: Doc me
 * 
 * @author keke <keke@codehaus.org>
 * @version
 * @revision $Revision:$
 */
public class TagResource extends Resource {

    private static final Logger  LOG = LoggerFactory
                                             .getLogger(TagResource.class);
    private RepresentationHelper repHelper;
    private Collection<TagItem>  tagItems;
    private TagService           tagService;
    private String               type;

    @Override
    public void acceptRepresentation(final Representation entity)
            throws ResourceException {
        final Form form = new Form(entity);
        final String tagName = form.getFirstValue("tags");
        final String about = form.getFirstValue("about");

        if (StringUtils.isEmpty(tagName) || StringUtils.isEmpty(about)) {
            if (LOG.isWarnEnabled()) {
                LOG.warn("tag and about should not be null");
            }
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
        } else {
            if (LOG.isDebugEnabled()) {
                LOG.debug("To tag {} by {}", new Object[] { about, tagName });
            }
            try {                
                final Representation rep = repHelper.toRepresentation("tags",
                        tagService.tag(tagName.split(","), new URI(about)),
                        new Variant(MediaType.APPLICATION_JSON));
                if (rep != null) {
                    getResponse().setEntity(rep);
                }
            } catch (final URISyntaxException e) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn(e.getMessage());
                }
                getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            }
        }
    }

    @Override
    public void init(final Context context, final Request request,
            final Response response) {
        super.init(context, request, response);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Initialze...");
        }
        if (request.getMethod().equals(Method.GET)) {
            initGet();
        } else if (request.getMethod().equals(Method.POST)) {
            initPost();
        }
    }

    @Override
    public Representation represent(final Variant variant)
            throws ResourceException {
        final Representation rep = repHelper.toRepresentation("tag", tagItems,
                variant);
        if (rep == null) {
            getResponse().setStatus(Status.CLIENT_ERROR_NOT_ACCEPTABLE,
                    "Type " + variant.getMediaType());
        }
        return rep;
    }

    public void setRepHelper(final RepresentationHelper repHelper) {
        this.repHelper = repHelper;
    }

    public void setTagService(final TagService tagService) {
        this.tagService = tagService;
    }

    private void initGet() {
        final String tagName = (String) getRequest().getAttributes().get("tag");
        tagItems = tagService.getTagItemsByName(tagName);
        type = (String) getRequest().getAttributes().get("type");
        if (StringUtils.isEmpty(type)) {
            type = "html";
        }
        getVariants().add(
                new Variant(MediaType
                        .valueOf(FileTypeMap.getDefaultFileTypeMap()
                                .getContentType("this." + type))));
    }

    private void initPost() {
        setModifiable(true);
    }

}
